package com.uduemc.biso.node.web.api.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.core.utils.RestResult;
import com.uduemc.biso.node.core.dto.FeignHrepertoryClearByList;
import com.uduemc.biso.node.core.dto.hrepertory.FeignFindInfosByHostIdTypesIds;
import com.uduemc.biso.node.core.entities.HRepertory;
import com.uduemc.biso.node.core.entities.HRepertoryLabel;
import com.uduemc.biso.node.core.feign.HRepertoryFeign;
import com.uduemc.biso.node.core.feign.HRepertoryLabelFeign;
import com.uduemc.biso.node.core.node.extities.RepertoryLabelTableData;
import com.uduemc.biso.node.core.node.feign.NRepertoryFeign;
import com.uduemc.biso.node.core.property.GlobalProperties;
import com.uduemc.biso.node.core.utils.FilterResponse;
import com.uduemc.biso.node.core.utils.LinkUtil;
import com.uduemc.biso.node.core.utils.RestResultUtil;
import com.uduemc.biso.node.core.utils.SitePathUtil;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.pojo.ResponseRepertory;
import com.uduemc.biso.node.web.api.service.RepertoryService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;

@Service
public class RepertoryServiceImpl implements RepertoryService {

	@Autowired
	private HRepertoryLabelFeign hRepertoryLabelFeign;

	@Autowired
	private HRepertoryFeign hRepertoryFeign;

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private NRepertoryFeign nRepertoryFeign;

	@Autowired
	private GlobalProperties globalProperties;

	@Override
	public List<HRepertoryLabel> getCurrentAllRepertoryLabel() throws IOException {
		RestResult restResult = hRepertoryLabelFeign.findByHostId(requestHolder.getHost().getId());
		JavaType valueType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, HRepertoryLabel.class);
		@SuppressWarnings("unchecked")
		ArrayList<HRepertoryLabel> data = (ArrayList<HRepertoryLabel>) RestResultUtil.data(restResult, valueType);
		return data;
	}

	@Override
	public HRepertoryLabel getInfoByIdHostId(long id, long hostId) throws IOException {
		RestResult restResult = hRepertoryLabelFeign.findByIdHostId(id, hostId);
		HRepertoryLabel data = RestResultUtil.data(restResult, HRepertoryLabel.class);
		return data;
	}

	@Override
	public PageInfo<HRepertory> getCurrentAndResponseRepertory(ResponseRepertory responseRepertory) throws IOException {
		short[] type = responseRepertory.getType();
		if (ArrayUtil.isEmpty(type)) {
			type = new short[] { -1 };
		}
		String[] suffix = responseRepertory.getSuffix();
		if (suffix == null) {
			suffix = new String[0];
		}
		RestResult restResult = hRepertoryFeign.findByWhereAndPage(requestHolder.getHost().getId().longValue(), responseRepertory.getLabelId(),
				responseRepertory.getOriginalFilename(), type, suffix, (short) 0, responseRepertory.getPage(), responseRepertory.getSize(), "`id` DESC");
		@SuppressWarnings("unchecked")
		PageInfo<HRepertory> data = (PageInfo<HRepertory>) RestResultUtil.data(restResult, new TypeReference<PageInfo<HRepertory>>() {
		});
		return data;
	}

	@Override
	public PageInfo<HRepertory> getCurrentAndResponseRepertoryRefuse(ResponseRepertory responseRepertory) throws IOException {
		short[] type = responseRepertory.getType();
		if (ArrayUtil.isEmpty(type)) {
			type = new short[] { -1 };
		}
		String[] suffix = responseRepertory.getSuffix();
		if (suffix == null) {
			suffix = new String[0];
		}
		RestResult restResult = hRepertoryFeign.findByWhereAndPage(requestHolder.getHost().getId().longValue(), responseRepertory.getLabelId(),
				responseRepertory.getOriginalFilename(), type, suffix, (short) 1, responseRepertory.getPage(), responseRepertory.getSize(), "`id` DESC");
		@SuppressWarnings("unchecked")
		PageInfo<HRepertory> data = (PageInfo<HRepertory>) RestResultUtil.data(restResult, new TypeReference<PageInfo<HRepertory>>() {
		});
		return data;
	}

	@Override
	public HRepertory getInfoByid(long id) throws IOException {
		RestResult restResult = hRepertoryFeign.findOne(id);
		HRepertory data = RestResultUtil.data(restResult, HRepertory.class);
		return data;
	}

	@Override
	public HRepertory findByHostIdAndId(long id, long hostId) throws IOException {
		RestResult restResult = hRepertoryFeign.findByHostIdAndId(id, hostId);
		HRepertory data = RestResultUtil.data(restResult, HRepertory.class);
		return data;
	}

	@Override
	public HRepertory updateById(HRepertory hRepertory) throws IOException {
		RestResult restResult = hRepertoryFeign.updateById(hRepertory);
		HRepertory data = RestResultUtil.data(restResult, HRepertory.class);
		return data;
	}

	@Override
	public boolean delete(long id) throws IOException {
		if (id < 1) {
			return false;
		}
		List<Long> ids = new ArrayList<>();
		ids.add(id);
		return delete(ids);
	}

	@Override
	public boolean delete(List<Long> ids) throws IOException {
		Long[] array = ids.stream().toArray(Long[]::new);
		RestResult restResult = hRepertoryFeign.deleteByList(array);
		JavaType valueType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, Long.class);
		@SuppressWarnings("unchecked")
		List<Long> data = (List<Long>) RestResultUtil.data(restResult, valueType);
		if (data.size() == ids.size()) {
			return true;
		}
		return false;
	}

	@Override
	public List<RepertoryLabelTableData> getCurrentAllLabelForTabledata() throws IOException {
		RestResult restResult = nRepertoryFeign.getRepertoryLabelTableDataList(requestHolder.getHost().getId().longValue());
		@SuppressWarnings("unchecked")
		List<RepertoryLabelTableData> data = (List<RepertoryLabelTableData>) RestResultUtil.data(restResult,
				new TypeReference<List<RepertoryLabelTableData>>() {
				});
		return data;
	}

	@Override
	public HRepertoryLabel labelSave(long id, String name) throws IOException {
		HRepertoryLabel hRepertoryLabel = null;
		HRepertoryLabel data = null;
		if (id > 0) {
			// 修改
			hRepertoryLabel = getInfoByIdHostId(id, requestHolder.getHost().getId().longValue());
			if (hRepertoryLabel == null) {
				return null;
			}
			hRepertoryLabel.setName(name);
			RestResult restResult = hRepertoryLabelFeign.updateById(hRepertoryLabel);
			data = RestResultUtil.data(restResult, HRepertoryLabel.class);
		} else {
			hRepertoryLabel = new HRepertoryLabel();
			hRepertoryLabel.setHostId(requestHolder.getHost().getId()).setName(name).setType((short) 0);
			RestResult restResult = hRepertoryLabelFeign.insert(hRepertoryLabel);
			data = RestResultUtil.data(restResult, HRepertoryLabel.class);
		}
		return data;
	}

	@Override
	public boolean labelDelete(HRepertoryLabel hRepertoryLabel) throws IOException {
		if (hRepertoryLabel.getType().shortValue() != (short) 0) {
			return false;
		}
		RestResult restResult = hRepertoryLabelFeign.deleteById(hRepertoryLabel.getId());
		RestResultUtil.data(restResult, HRepertoryLabel.class, true);
		return true;
	}

	@Override
	public boolean reductionItem(HRepertory hRepertory) throws IOException {
		List<Long> ids = new ArrayList<>();
		ids.add(hRepertory.getId().longValue());
		return reductionItems(ids);
	}

	@Override
	public boolean reductionCurrentItem(long id) throws IOException {
		HRepertory infoByid = getInfoByid(id);
		if (infoByid.getHostId().longValue() != requestHolder.getHost().getId().longValue()) {
			return false;
		}
		return reductionItem(infoByid);
	}

	@Override
	public boolean reductionItems(List<Long> ids) throws IOException {
		Long[] array = ids.stream().toArray(Long[]::new);
		RestResult restResult = hRepertoryFeign.reductionByList(array);
		JavaType valueType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, Long.class);
		@SuppressWarnings("unchecked")
		List<Long> data = (List<Long>) RestResultUtil.data(restResult, valueType);
		if (data.size() == ids.size()) {
			return true;
		}
		return false;
	}

	@Override
	public boolean reductionCurrentAll() throws IOException {
		RestResult restResult = hRepertoryFeign.reductionAll(requestHolder.getHost().getId().longValue());
		Boolean data = RestResultUtil.data(restResult, Boolean.class);
		return data;
	}

	@Override
	public boolean clearItems(List<Long> ids) throws IOException {
		String basePath = globalProperties.getSite().getBasePath();
		FeignHrepertoryClearByList feignHrepertoryClearByList = new FeignHrepertoryClearByList();
		feignHrepertoryClearByList.setBasePath(basePath).setRepertoryIds(ids);
		RestResult restResult = hRepertoryFeign.clearByList(feignHrepertoryClearByList);
		JavaType valueType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, Long.class);
		@SuppressWarnings("unchecked")
		List<Long> data = (List<Long>) RestResultUtil.data(restResult, valueType);
		if (data.size() == ids.size()) {
			return true;
		}
		return false;
	}

	@Override
	public JsonResult clearCurrentAll() throws IOException {
		Long hostId = requestHolder.getHost().getId();
		// 获取存在绑定SSL证书的，且在回收站的资源数据
		RestResult restResult = hRepertoryFeign.infosBySslInRsefuse(hostId);
		@SuppressWarnings("unchecked")
		List<HRepertory> listHRepertory = (ArrayList<HRepertory>) RestResultUtil.data(restResult, new TypeReference<ArrayList<HRepertory>>() {
		});
		if (CollUtil.isNotEmpty(listHRepertory)) {
			return JsonResult.messageError("域名已绑定的SSL证书不能清除，请先删除绑定的SSL证书后再进行清除！");
		}

		String basePath = globalProperties.getSite().getBasePath();
		restResult = hRepertoryFeign.clearAll(hostId, basePath);
		Boolean data = RestResultUtil.data(restResult, Boolean.class);
		if (data == null || data.booleanValue() == false) {
			return JsonResult.assistance();
		}
		return null;
	}

	@Override
	public boolean existCurrentByRepertoryIds(List<Long> repertoryIds) throws IOException {
		RestResult restResult = hRepertoryFeign.existByHostIdAndRepertoryIds(requestHolder.getHost().getId(), repertoryIds);
		return RestResultUtil.data(restResult, Boolean.class);
	}

	@Override
	public HRepertory insertCurrentOutsideImageLink(String link) throws IOException {
		HRepertory hRepertory = new HRepertory();
		hRepertory.setHostId(requestHolder.getHost().getId()).setLabelId(0L).setType((short) 4).setLink(link);

		// 通过链接获取图片的名称以及图片的后缀
		String imageSuffixByLink = LinkUtil.getImageSuffixByLink(link);
		hRepertory.setSuffix(imageSuffixByLink).setOriginalFilename("未定义图片名." + imageSuffixByLink);

		RestResult restResult = hRepertoryFeign.insert(hRepertory);
		HRepertory data = RestResultUtil.data(restResult, HRepertory.class);
		return data;
	}

	@Override
	public JsonResult updateCurrentOriginalFilename(long id, String oname) throws IOException {
		RestResult restResult = hRepertoryFeign.findOne(id);
		HRepertory data = RestResultUtil.data(restResult, HRepertory.class);
		if (data == null || data.getId() == null || data.getId().longValue() < 1) {
			return JsonResult.ok();
		}
		if (data.getHostId().longValue() != requestHolder.getHost().getId().longValue()) {
			return JsonResult.ok();
		}

		// 外部链接图片修改资源名称！
		if (data.getType() != null && data.getType().shortValue() == 4) {
			data.setOriginalFilename(oname);
			RestResult updateById = hRepertoryFeign.updateById(data);
			HRepertory update = RestResultUtil.data(updateById, HRepertory.class);
			if (update == null || update.getId() == null || update.getId().longValue() < 1) {
				return null;
			}
			return JsonResult.ok(FilterResponse.filterRepertoryInfo(update));
		}

		String basePath = globalProperties.getSite().getBasePath();
		Host host = requestHolder.getHost();
		// 通过 basePath 以及 code 获取 用户的目录
		String userPathByCode = SitePathUtil.getUserPathByCode(basePath, host.getRandomCode());
		String filepath = data.getFilepath();
		String filefullpath = userPathByCode + "/" + filepath;
		File file = FileUtil.file(filefullpath);
		if (!file.isFile()) {
			return JsonResult.assistance();
		}

		// 判断是否已经存在此文件名称
		String directory = file.getParent();
		String nFilefullpath = directory + File.separator + oname;
		File nfile = FileUtil.file(directory + File.separator + oname);
		if (nfile.isFile()) {
			return JsonResult.messageWarning(oname + " 文件名在系统目录下已存在！");
		}

		File rename = FileUtil.rename(file, oname, false);
		if (!rename.isFile()) {
			return JsonResult.assistance();
		}
		String nFilepath = nFilefullpath.substring(userPathByCode.length() + 1);

		data.setOriginalFilename(oname);
		data.setFilepath(nFilepath);
		RestResult updateById = hRepertoryFeign.updateById(data);
		HRepertory update = RestResultUtil.data(updateById, HRepertory.class);
		if (update == null || update.getId() == null || update.getId().longValue() < 1) {
			return null;
		}
		return JsonResult.ok(FilterResponse.filterRepertoryInfo(update));
	}

	@Override
	public int totalCurrentType(short type) throws IOException {
		RestResult restResult = hRepertoryFeign.totalType(requestHolder.getHost().getId(), type, (short) 0);
		Integer total = RestResultUtil.data(restResult, Integer.class);
		return total;
	}

	@Override
	public Map<String, HRepertory> makeExternalLinks(List<String> externalLinks) throws IOException {
		RestResult restResult = hRepertoryFeign.makeExternalLinks(requestHolder.getHost().getId(), externalLinks);
		@SuppressWarnings("unchecked")
		Map<String, HRepertory> data = (Map<String, HRepertory>) RestResultUtil.data(restResult, new TypeReference<Map<String, HRepertory>>() {
		});
		return data;
	}

	@Override
	public List<HRepertory> findInfosByHostIdTypesIds(long hostId, List<Short> types, List<Long> ids) throws IOException {
		FeignFindInfosByHostIdTypesIds params = new FeignFindInfosByHostIdTypesIds();
		params.setHostId(hostId).setTypes(types).setIds(ids);
		RestResult restResult = hRepertoryFeign.findInfosByHostIdTypesIds(params);
		@SuppressWarnings("unchecked")
		List<HRepertory> data = (ArrayList<HRepertory>) RestResultUtil.data(restResult, new TypeReference<ArrayList<HRepertory>>() {
		});
		return data;
	}

}
